#include "wx/wxprec.h"
#ifndef WXPRECOMP
#include "wx/image.h"
#endif

#include "wx/html/forcelnk.h"
#include "wx/html/m_templ.h"
#include "wx/html/htmlwin.h"

FORCE_LINK_ME( m_layout )

#include <stdlib.h>


class wxHtmlPageBreakCell : public wxHtmlCell {
  public:
    wxHtmlPageBreakCell() {}

    bool AdjustPagebreak( int* pagebreak,
                          wxArrayInt& known_pagebreaks ) const;

    void Draw( wxDC& ( dc ),
               int ( x ), int ( y ),
               int ( view_y1 ), int ( view_y2 ),
               wxHtmlRenderingInfo& ( info ) ) {}

  private:
    DECLARE_NO_COPY_CLASS( wxHtmlPageBreakCell )
};

extern "C" int wxCMPFUNC_CONV wxInteger_compare( void const* i0, void const* i1 ) {
  return *( int* )i0 - *( int* )i1;
}

bool wxHtmlPageBreakCell::AdjustPagebreak( int* pagebreak, wxArrayInt& known_pagebreaks ) const {
  if( known_pagebreaks.Count() == 0 || *pagebreak <= m_PosY ) {
    return false;
  }
  int total_height = m_PosY;
  for( wxHtmlCell *parent = GetParent(); parent; parent = parent->GetParent() ) {
    total_height += parent->GetPosY();
  }
  int where = known_pagebreaks.Index( total_height );
  if( wxNOT_FOUND != where ) {
    return false;
  } else {
    *pagebreak = m_PosY;
    return true;
  }
}

TAG_HANDLER_BEGIN( P, "P" )
TAG_HANDLER_CONSTR( P ) { }

TAG_HANDLER_PROC( tag ) {
  if( m_WParser->GetContainer()->GetFirstChild() != NULL ) {
    m_WParser->CloseContainer();
    m_WParser->OpenContainer();
  }
  m_WParser->GetContainer()->SetIndent( m_WParser->GetCharHeight(), wxHTML_INDENT_TOP );
  m_WParser->GetContainer()->SetAlign( tag );
  return false;
}

TAG_HANDLER_END( P )
TAG_HANDLER_BEGIN( BR, "BR" )
TAG_HANDLER_CONSTR( BR ) { }

TAG_HANDLER_PROC( tag ) {
  int al = m_WParser->GetContainer()->GetAlignHor();
  wxHtmlContainerCell *c;
  m_WParser->CloseContainer();
  c = m_WParser->OpenContainer();
  c->SetAlignHor( al );
  c->SetAlign( tag );
  c->SetMinHeight( m_WParser->GetCharHeight() );
  return false;
}

TAG_HANDLER_END( BR )
TAG_HANDLER_BEGIN( CENTER, "CENTER" )
TAG_HANDLER_CONSTR( CENTER ) { }

TAG_HANDLER_PROC( tag ) {
  int old = m_WParser->GetAlign();
  wxHtmlContainerCell *c = m_WParser->GetContainer();
  m_WParser->SetAlign( wxHTML_ALIGN_CENTER );
  if( c->GetFirstChild() != NULL ) {
    m_WParser->CloseContainer();
    m_WParser->OpenContainer();
  } else
  { c->SetAlignHor( wxHTML_ALIGN_CENTER ); }
  if( tag.HasEnding() ) {
    ParseInner( tag );
    m_WParser->SetAlign( old );
    if( c->GetFirstChild() != NULL ) {
      m_WParser->CloseContainer();
      m_WParser->OpenContainer();
    } else
    { c->SetAlignHor( old ); }
    return true;
  } else
  { return false; }
}

TAG_HANDLER_END( CENTER )
TAG_HANDLER_BEGIN( DIV, "DIV" )
TAG_HANDLER_CONSTR( DIV ) { }

TAG_HANDLER_PROC( tag ) {
  if( tag.HasParam( wxT( "STYLE" ) ) ) {
    if( tag.GetParam( wxT( "STYLE" ) ).IsSameAs( wxT( "PAGE-BREAK-BEFORE:ALWAYS" ), false ) ) {
      m_WParser->CloseContainer();
      m_WParser->OpenContainer()->InsertCell( new wxHtmlPageBreakCell );
      m_WParser->CloseContainer();
      m_WParser->OpenContainer();
      return false;
    } else
    { return false; }
  } else if( tag.HasParam( wxT( "ALIGN" ) ) ) {
    int old = m_WParser->GetAlign();
    wxHtmlContainerCell *c = m_WParser->GetContainer();
    if( c->GetFirstChild() != NULL ) {
      m_WParser->CloseContainer();
      m_WParser->OpenContainer();
      c = m_WParser->GetContainer();
      c->SetAlign( tag );
      m_WParser->SetAlign( c->GetAlignHor() );
    } else {
      c->SetAlign( tag );
      m_WParser->SetAlign( c->GetAlignHor() );
    }
    ParseInner( tag );
    m_WParser->SetAlign( old );
    if( c->GetFirstChild() != NULL ) {
      m_WParser->CloseContainer();
      m_WParser->OpenContainer();
    } else
    { c->SetAlignHor( old ); }
    return true;
  } else {
    int al = m_WParser->GetContainer()->GetAlignHor();
    wxHtmlContainerCell *c;
    m_WParser->CloseContainer();
    c = m_WParser->OpenContainer();
    c->SetAlignHor( al );
    c->SetAlign( tag );
    c->SetMinHeight( m_WParser->GetCharHeight() );
    return false;
  }
}

TAG_HANDLER_END( DIV )
TAG_HANDLER_BEGIN( TITLE, "TITLE" )
TAG_HANDLER_CONSTR( TITLE ) { }

TAG_HANDLER_PROC( tag ) {
  wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface();
  if( winIface ) {
    wxString title = m_WParser->GetSource()->Mid(
                       tag.GetBeginPos(),
                       tag.GetEndPos1() - tag.GetBeginPos() );
    title = m_WParser->GetEntitiesParser()->Parse( title );
    winIface->SetHTMLWindowTitle( title );
  }
  return true;
}

TAG_HANDLER_END( TITLE )
TAG_HANDLER_BEGIN( BODY, "BODY" )
TAG_HANDLER_CONSTR( BODY ) { }

TAG_HANDLER_PROC( tag ) {
  wxColour clr;
  if( tag.GetParamAsColour( wxT( "TEXT" ), &clr ) ) {
    m_WParser->SetActualColor( clr );
    m_WParser->GetContainer()->InsertCell( new wxHtmlColourCell( clr ) );
  }
  if( tag.GetParamAsColour( wxT( "LINK" ), &clr ) ) {
    m_WParser->SetLinkColor( clr );
  }
  wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface();
  if( !winIface ) {
    return false;
  }
  if( tag.HasParam( wxT( "BACKGROUND" ) ) ) {
    wxFSFile *fileBgImage = m_WParser->OpenURL
                            (
                              wxHTML_URL_IMAGE,
                              tag.GetParam( wxT( "BACKGROUND" ) )
                            );
    if( fileBgImage ) {
      wxInputStream *is = fileBgImage->GetStream();
      if( is ) {
        #if !defined(__WXMSW__) || wxUSE_WXDIB
        wxImage image( *is );
        if( image.Ok() ) {
          winIface->SetHTMLBackgroundImage( image );
        }
        #endif
      }
      delete fileBgImage;
    }
  }
  if( tag.GetParamAsColour( wxT( "BGCOLOR" ), &clr ) ) {
    m_WParser->GetContainer()->InsertCell(
      new wxHtmlColourCell( clr, wxHTML_CLR_BACKGROUND ) );
    winIface->SetHTMLBackgroundColour( clr );
  }
  return false;
}

TAG_HANDLER_END( BODY )
TAG_HANDLER_BEGIN( BLOCKQUOTE, "BLOCKQUOTE" )
TAG_HANDLER_CONSTR( BLOCKQUOTE ) { }

TAG_HANDLER_PROC( tag ) {
  wxHtmlContainerCell *c;
  m_WParser->CloseContainer();
  c = m_WParser->OpenContainer();
  if( c->GetAlignHor() == wxHTML_ALIGN_RIGHT ) {
    c->SetIndent( 5 * m_WParser->GetCharWidth(), wxHTML_INDENT_RIGHT );
  } else
  { c->SetIndent( 5 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT ); }
  c->SetIndent( m_WParser->GetCharHeight(), wxHTML_INDENT_TOP );
  m_WParser->OpenContainer();
  ParseInner( tag );
  c = m_WParser->CloseContainer();
  c->SetIndent( m_WParser->GetCharHeight(), wxHTML_INDENT_BOTTOM );
  m_WParser->CloseContainer();
  m_WParser->OpenContainer();
  return true;
}

TAG_HANDLER_END( BLOCKQUOTE )
TAG_HANDLER_BEGIN( SUBSUP, "SUB,SUP" )

TAG_HANDLER_PROC( tag ) {
  bool issub = ( tag.GetName() == wxT( "SUB" ) );
  wxHtmlScriptMode oldmode = m_WParser->GetScriptMode();
  int oldbase = m_WParser->GetScriptBaseline();
  int oldsize = m_WParser->GetFontSize();
  wxHtmlContainerCell *cont = m_WParser->GetContainer();
  wxHtmlCell *c = cont->GetLastChild();
  m_WParser->SetScriptMode( issub ? wxHTML_SCRIPT_SUB : wxHTML_SCRIPT_SUP );
  m_WParser->SetScriptBaseline(
    oldbase + c ? c->GetScriptBaseline() : 0 );
  m_WParser->SetFontSize( m_WParser->GetFontSize() - 2 );
  cont->InsertCell( new wxHtmlFontCell( m_WParser->CreateCurrentFont() ) );
  ParseInner( tag );
  m_WParser->SetFontSize( oldsize );
  m_WParser->GetContainer()->InsertCell(
    new wxHtmlFontCell( m_WParser->CreateCurrentFont() ) );
  m_WParser->SetScriptBaseline( oldbase );
  m_WParser->SetScriptMode( oldmode );
  return true;
}

TAG_HANDLER_END( SUBSUP )
TAG_HANDLER_BEGIN( DoNothing, "SCRIPT" )
TAG_HANDLER_CONSTR( DoNothing ) { }

TAG_HANDLER_PROC( ( tag ) ) {
  return true;
}

TAG_HANDLER_END( DoNothing )
TAGS_MODULE_BEGIN( Layout )
TAGS_MODULE_ADD( P )
TAGS_MODULE_ADD( BR )
TAGS_MODULE_ADD( CENTER )
TAGS_MODULE_ADD( DIV )
TAGS_MODULE_ADD( TITLE )
TAGS_MODULE_ADD( BODY )
TAGS_MODULE_ADD( BLOCKQUOTE )
TAGS_MODULE_ADD( SUBSUP )
TAGS_MODULE_ADD( DoNothing )
TAGS_MODULE_END( Layout )

